/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package org.cedict.domain;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.NamedQuery;
import javax.persistence.OneToMany;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.builder.ToStringBuilder;
import org.hibernate.annotations.Index;
import org.hibernate.annotations.Table;

/**
 *
 * @author Andrew
 */
@Entity
@javax.persistence.Table(name="cedict")
@Table(appliesTo="cedict", indexes = { @Index(name="andrew_test", columnNames={"traditionalCharacters", "pinyin"})})
@NamedQuery(name="findByTraditionalAndPinyin",
    query="select c from UTF8CedictRow c where " +
    "c.traditionalCharacters = :traditionalCharacters and c.pinyin = :pinyin")
    
public class UTF8CedictRow implements Serializable {

    @Id
    @GeneratedValue
    private Long id;
    @Column(nullable=false, length=31)
    private String traditionalCharacters;
    @Column(nullable=false, length=31)
    private String simplifiedCharacters;
    @Column(nullable=false, length=255)
    private String pinyin;
    // FIXME: this should simply be a List of Strings
    @OneToMany(cascade=CascadeType.ALL)
    private List<CedictRowDefinition> definitions;

    public UTF8CedictRow() {
        definitions = new ArrayList<CedictRowDefinition>();
    }

    public UTF8CedictRow(String traditionalCharacters,
            String simplifiedCharacters, String pinyin,
            List<String> stringDefinitions) {
        this.traditionalCharacters = traditionalCharacters;
        this.simplifiedCharacters = simplifiedCharacters;
        this.pinyin = pinyin;
        int order = 0;
        definitions = new ArrayList<CedictRowDefinition>();
        for (String definition : stringDefinitions) {
            definitions.add(new CedictRowDefinition(this, order++, definition));
        }
    }

    /**
     * @return the id
     */
    public Long getId() {
        return id;
    }

    /**
     * @param id the id to set
     */
    public void setId(Long id) {
        this.id = id;
    }

    /**
     * @return the traditionalCharacters
     */
    public String getTraditionalCharacters() {
        return traditionalCharacters;
    }

    /**
     * @param traditionalCharacters the traditionalCharacters to set
     */
    public void setTraditionalCharacters(String traditionalCharacters) {
        this.traditionalCharacters = traditionalCharacters;
    }

    /**
     * @return the simplifiedCharacters
     */
    public String getSimplifiedCharacters() {
        return simplifiedCharacters;
    }

    /**
     * @param simplifiedCharacters the simplifiedCharacters to set
     */
    public void setSimplifiedCharacters(String simplifiedCharacters) {
        this.simplifiedCharacters = simplifiedCharacters;
    }

    /**
     * @return the pinyin
     */
    public String getPinyin() {
        return pinyin;
    }

    /**
     * @param pinyin the pinyin to set
     */
    public void setPinyin(String pinyin) {
        this.pinyin = pinyin;
    }

    /**
     * @return the definitions
     */
    public List<CedictRowDefinition> getDefinitions() {
        return definitions;
    }

    /**
     * @param definitions the definitions to set
     */
    public void setDefinitions(List<CedictRowDefinition> definitions) {
        this.definitions = definitions;
    }

    @Override
    public int hashCode() {
        int hash = 5;
        hash = 37 * hash + (this.traditionalCharacters != null ? this.traditionalCharacters.hashCode() : 0);
        hash = 37 * hash + (this.simplifiedCharacters != null ? this.simplifiedCharacters.hashCode() : 0);
        hash = 37 * hash + (this.pinyin != null ? this.pinyin.hashCode() : 0);
        hash = 37 * hash + (this.definitions != null ? this.definitions.hashCode() : 0);
        return hash;
    }

    @Override
    public boolean equals(Object obj) {
        if (obj == null) {
            return false;
        }
        if (getClass() != obj.getClass()) {
            return false;
        }
        final UTF8CedictRow other = (UTF8CedictRow) obj;
        if ((this.traditionalCharacters == null) ? (other.traditionalCharacters != null) : !this.traditionalCharacters.equals(other.traditionalCharacters)) {
            return false;
        }
        if ((this.simplifiedCharacters == null) ? (other.simplifiedCharacters != null) : !this.simplifiedCharacters.equals(other.simplifiedCharacters)) {
            return false;
        }
        if ((this.pinyin == null) ? (other.pinyin != null) : !this.pinyin.equals(other.pinyin)) {
            return false;
        }
        if (this.definitions != other.definitions && (this.definitions == null || !this.definitions.equals(other.definitions))) {
            return false;
        }
        return true;
    }

    @Override
    public String toString() {
        return new ToStringBuilder(this).
                append("traditional", traditionalCharacters).
                append("simplified", simplifiedCharacters).
                append("pinyin", pinyin).
                append("definitions", StringUtils.join(definitions, "/")).
                toString();
    }

    public void setDefinitions(String... defs) {
        this.definitions = new ArrayList<CedictRowDefinition>();
        int order = 0;
        for (String def : defs) {
            definitions.add(new CedictRowDefinition(this, order++, def));
        }
    }

    public void update(UTF8CedictRow cedictRow) {

    }

    public List<String> getStringDefinitions() {
        List<String> stringDefinitions = new ArrayList();
        for (CedictRowDefinition def : definitions) {
            stringDefinitions.add(def.getDefinition());
        }
        return stringDefinitions;
    }

    public void setStringDefinitions(List<String> defs) {
        int i = 0;
        for (String def : defs) {
            CedictRowDefinition currentDef = null;
            if (definitions.size() < i) {
                currentDef = definitions.get(i++);
            }

            if (currentDef != null) {
                currentDef.setDefinition(def);
            } else {
                currentDef = new CedictRowDefinition(this, i, def);
                definitions.add(currentDef);
            }
        }
        for (int j = i; j < definitions.size(); j++) {
            definitions.remove(j);
        }
    }

}
